package kernel

import (
	"encoding/json"
	"io"
	"net/http"
)

var (
	DefaultPageSize int = 10
)

func ShouldBindJSON(r *http.Request, obj any) error {
	// 读取请求体
	body, err := io.ReadAll(r.Body)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	err = json.Unmarshal(body, &obj)
	if err != nil {
		return err
	}
	return nil
}

// 分页
type Pagination struct {
	Page     int    `json:"page" form:"page"`           // 页码
	PageSize int    `json:"page_size" form:"page_size"` // 每页大小
	Keyword  string `json:"keyword" form:"keyword"`     //关键字
}

// 获取正确的page信息
func (i Pagination) GetPage() int {
	if i.Page <= 0 {
		return 1
	}
	return i.Page
}

// 过滤后的page size
func (i Pagination) GetSize() int {
	if i.PageSize <= 0 {
		return DefaultPageSize
	}
	return i.PageSize
}

// 计算数据库使用的Offset
func (i Pagination) Offset() int {
	return (i.GetPage() - 1) * i.GetSize()
}

var (
	DefaultSuccessCode    int    = 0
	DefaultSuccessMessage string = "success"
	DefalutErrorCode      int    = http.StatusBadRequest
)

type responseBody struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
}

func JSON(w http.ResponseWriter, code int, msg string, data any) {
	w.Header().Set("Content-Type", "application/json")
	b, err := json.Marshal(&responseBody{
		Code:    code,
		Message: msg,
		Data:    data,
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(b)
}

func Success(w http.ResponseWriter) {
	JSON(w, DefaultSuccessCode, DefaultSuccessMessage, nil)
}

func Data(w http.ResponseWriter, data any) {
	JSON(w, DefaultSuccessCode, DefaultSuccessMessage, data)
}

func Failure(w http.ResponseWriter, code int, message string) {
	JSON(w, code, message, nil)
}

// 错误输出
func Error(w http.ResponseWriter, err error) {
	w.WriteHeader(http.StatusBadRequest)
	Failure(w, DefalutErrorCode, err.Error())
}

// 列表数据
func List(w http.ResponseWriter, total int64, page, pageSize int, list any, opts ...func(h map[string]any) map[string]any) {
	data := map[string]any{
		"total":     total,
		"page":      page,
		"page_size": pageSize,
		"list":      list,
	}
	for _, opt := range opts {
		data = opt(data)
	}
	Data(w, data)
}

// 快速错误处理
// 存在错误时返回true，并设置错误信息
func Qe(w http.ResponseWriter, err error, opts ...func(err error) error) bool {
	if err != nil {
		// 是否触发其它错误
		for _, opt := range opts {
			if frr := opt(err); frr != nil {
				Error(w, frr)
				return true
			}
		}
		Error(w, err)
		return true
	}
	return false
}
